package com.oig.sys.auth.service.impl;

import cn.hutool.core.util.StrUtil;
import com.oig.common.constants.CommonConstants;
import com.oig.common.constants.CommonEnum;
import com.oig.common.exception.BadRequestException;
import com.oig.sys.auth.constants.AuthEnums;
import com.oig.sys.auth.dao.ITbSystemDao;
import com.oig.sys.auth.dto.SystemDto;
import com.oig.sys.auth.entity.TbSystem;
import com.oig.sys.auth.service.*;
import com.oig.sys.auth.vo.SystemVo;
import com.oig.sys.security.util.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * @author wuxl
 */
@Service
@Slf4j
public class TbSystemServiceImpl implements ITbSystemService {

	private final ITbSystemDao tbSystemDao;
	private final ITbResourceService resourceService;
	private final ITbRoleSystemService roleSystemService;
	private final ITbUserRoleService userRoleService;
	private final ITbUserService userService;

	@Autowired
	public TbSystemServiceImpl(ITbSystemDao tbSystemDao,
							   ITbResourceService resourceService,
							   ITbRoleSystemService roleSystemService,
							   ITbUserRoleService userRoleService,
							   ITbUserService userService){
		 this.tbSystemDao = tbSystemDao;
		 this.resourceService = resourceService;
		 this.roleSystemService = roleSystemService;
		 this.userRoleService = userRoleService;
		 this.userService = userService;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public SystemVo addSystem(SystemDto systemDto) {
		if (AuthEnums.SystemTypeEnum.SYSTEM_OUT.getCode().equals(systemDto.getSystemType())){
			if (StrUtil.isBlank(systemDto.getSystemUrl())){
				throw new BadRequestException("外部应用url必填") ;
			}
		}
		TbSystem system = new TbSystem() ;
		BeanUtils.copyProperties(systemDto, system, "id");
		system.setCreateUserId(SecurityUtil.getDefineUserMain().getId());
		system.setCreateTime(new Date());
		system.setCreateUserName(SecurityUtil.getDefineUserMain().getRealName());
		system.setNoDelFlag(CommonEnum.FlagEnum.TRUE_FLAG.getCode());
		system.setStatus(CommonEnum.CommonStatusEnum.OK.getCode());
		if (systemDto.getSort()==null){
			system.setSort(3);
		}
		this.tbSystemDao.save(system) ;
		SystemVo systemVo = new SystemVo() ;
		BeanUtils.copyProperties(system, systemVo);
		return systemVo;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public SystemVo updateSystem(SystemDto systemDto) {
		TbSystem system = this.tbSystemDao.getTbSystemById(systemDto.getId()) ;
		log.debug("dto={},entity={}", systemDto, system);
		if (system==null){
			throw new BadRequestException("id错误，记录不存在") ;
		}
		if (AuthEnums.SystemTypeEnum.SYSTEM_OUT.getCode().equals(systemDto.getSystemType())){
			if (StrUtil.isBlank(systemDto.getSystemUrl())){
				throw new BadRequestException("外部应用url必填") ;
			}
		}
		if (systemDto.getSort()==null){
			systemDto.setSort(system.getSort());
		}
		if (!system.getSystemName().equals(systemDto.getSystemName())
				||(system.getImageUrl()!=null&&!system.getImageUrl().equals(systemDto.getImageUrl()))
				||(systemDto.getImageUrl()!=null&&!systemDto.getImageUrl().equals(system.getImageUrl()))){
			this.userService.updateUserDefSystemName(system.getId(), systemDto.getSystemName(), systemDto.getImageUrl());
		}
		BeanUtils.copyProperties(systemDto, system, "id");
		system.setLastUpdateTime(new Date());
		system.setLastUpdateId(SecurityUtil.getDefineUserMain().getId());
		system.setLastUpdateName(SecurityUtil.getDefineUserMain().getRealName());
		this.tbSystemDao.save(system) ;
		SystemVo systemVo = new SystemVo() ;
		BeanUtils.copyProperties(system, systemVo);
		return systemVo;
	}


	@Override
	public SystemVo getSystem(Integer id) {
		TbSystem system = this.tbSystemDao.getTbSystemById(id) ;
		if (system==null){
			throw new BadRequestException("id错误，记录不存在") ;
		}
		SystemVo systemVo = new SystemVo() ;
		BeanUtils.copyProperties(system, systemVo);
		return systemVo;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void cancelSystem(Integer systemId) {
		TbSystem system = this.tbSystemDao.getTbSystemById(systemId) ;
		if (system==null){
			throw new BadRequestException("id错误，记录不存在") ;
		}
		if (CommonEnum.FlagEnum.FALSE_FLAG.getCode().equals(system.getNoDelFlag())){
			throw new BadRequestException("不允许删除") ;
		}
		system.setStatus(CommonEnum.CommonStatusEnum.DEL.getCode());
		this.tbSystemDao.save(system) ;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void revertSystem(Integer systemId) {
		TbSystem system = this.tbSystemDao.getTbSystemById(systemId) ;
		if (system==null){
			throw new BadRequestException("id错误，记录不存在") ;
		}
		if (!CommonEnum.CommonStatusEnum.DEL.getCode().equals(system.getStatus())){
            throw new BadRequestException("非注销状态") ;
        }
		system.setStatus(CommonEnum.CommonStatusEnum.OK.getCode());
		this.tbSystemDao.save(system) ;
	}

	@Transactional
	@Override
	public void delSystem(Integer systemId) {
		TbSystem system = this.tbSystemDao.getTbSystemById(systemId) ;
		if (system==null){
			throw new BadRequestException("id错误，记录不存在") ;
		}
		if (!CommonEnum.CommonStatusEnum.DEL.getCode().equals(system.getStatus())){
			throw new BadRequestException("只有注销状态的应用才能清除数据") ;
		}
		this.resourceService.delResourceBySystemId(systemId);		//系统菜单数据
		this.roleSystemService.delRoleSystemBySystemId(systemId);	//系统权限关联数据
		this.userService.cleanUserDefSystem(systemId);	//用户的默认系统
		this.tbSystemDao.delete(system);
	}

	@Override
	public List<SystemVo> findSystem(String systemName, String systemTypes) {
		Specification<TbSystem> specification = new Specification<TbSystem>(){
			@Override
			@Nullable
			public Predicate toPredicate(@NonNull Root<TbSystem> root, @NonNull CriteriaQuery<?> criteriaQuery, @NonNull CriteriaBuilder criteriaBuilder) {
				List<Predicate> predicateList = new ArrayList<>();
				if (StrUtil.isNotBlank(systemName)){
					Path<String> systemNamePath = root.get("systemName");
					predicateList.add(criteriaBuilder.like(systemNamePath, "%"+systemName+"%"));
				}
				if (StrUtil.isNotBlank(systemTypes)){
					Path<String> systemTypePath = root.get("systemType");
					String[] sysTypes = systemTypes.split(CommonConstants.SEMICOLON_STR);
					CriteriaBuilder.In<String> inQ = criteriaBuilder.in(systemTypePath);
					for (String systemType : sysTypes){
						inQ.value(systemType);
					}
					predicateList.add(inQ);
				}
				if (SecurityUtil.getDefineUserMain().getTenantId()!=0){
					List<Integer> systemIdList = userRoleService.findAllOkSystemId(SecurityUtil.getDefineUserMain().getId());
					Path<Integer> idPath = root.get("id");
					CriteriaBuilder.In<Integer> inQ = criteriaBuilder.in(idPath);
					log.info("ids={}",systemIdList);

					for (Integer systemId : systemIdList){
						inQ.value(systemId);
					}
					predicateList.add(inQ);
				}
				criteriaQuery.where(predicateList.toArray(new Predicate[0]));
				return criteriaQuery.getRestriction();
			}
		};
		List<TbSystem> systemList  = this.tbSystemDao.findAll(specification);
		List<SystemVo> systemVoList = new ArrayList<>();
		for (TbSystem system : systemList){
			SystemVo systemVo = new SystemVo();
			BeanUtils.copyProperties(system,systemVo);
			systemVoList.add(systemVo);
		}
		return systemVoList;
	}



}
